二 Python基础之字符串和编码

字符编码

  • ASCII与Unicode的区别

ASCII编码是1个字节,而Unicode编码通常是2个字节。

  • 计算机系统通用的字符编码方式

在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换成UTF-8编码。

字符串

Python3的字符串中,使用Unicode编码,也就是说,Python的字符串支持多语言。

1
2
>>> print('测试python字符串')
测试python字符串

对于单个字符的编码,Python提供了ord()函数获取字符的整数表示chr()函数把编码转换成对应的字符:

1
2
3
4
5
6
7
8
>>> ord('A')
65
>>> chr(65)
'A'
>>> ord('中')
20013
>>> chr(20013)
'中'

由于Python的字符串类型是str,在内存中以Unicode表示,一个字符对应若干个字节。如果要在网络上传输或者保存到磁盘上,就需要把str变成以字节为单位bytes.

bytes类型的数据用带b前缀的单引号或双引号表示:

1
name = b'ABC'

注意:'ABC'b'ABC'虽然内容上一样,但是两者是有区别的,'ABC'strb'ABC'类型是bytes并且每个字符都只占用1个字节

str编码为bytes

可以将str类型的字符串编码为指定的bytes

  • 通过ASCII编码

英文的字符串我们可以用过ASCII编码,但是中文是不允许的,因为超过了ASCII的编码范围。中文我们用UTF-8即可:

1
2
3
4
>>> 'ABC'.encode('ascii')
b'ABC'
>>> '人民币'.encode('utf-8')
b'\xe4\xba\xba\xe6\xb0\x91\xe5\xb8\x81'

注:在bytes中,如果无法显示成ASCII字符的字节,使用\x##表示。

bytes解码为str

我们从网络或磁盘上读取到的都是字节流bytes,因此我们需要解码str,可以使用decode

1
2
3
4
>>> b'ABC'.decode('ascii')
'ABC'
>>> b'\xe4\xba\xba\xe6\xb0\x91\xe5\xb8\x81'.decode('utf-8')
'人民币'

如果bytes中只有一小部分字节是无效的,那么可以传入errors='ignore'来忽略错误的字节:

1
2
>>> b'\xe4\xba\xba\xe6\xb0\x91\xe5\xb8\x81\xaa\xbb\xcc'.decode('utf-8', errors='ignore')
'人民币'

如果不使用errors='ignore',则会报错

1
2
3
4
>>> b'\xe4\xba\xba\xe6\xb0\x91\xe5\xb8\x81\xaa\xbb\xcc'.decode('utf-8')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xaa in position 9: invalid start byte

计算字符数

可以使用len()函数来计算str的字符数,比如

1
2
3
4
>>> len('abc')
3
>>> len('我爱中国')
4

计算字节数

如果需要计算一个str类型的字节数,需要先将str编码成为bytes,然后使用len()函数计算

1
2
3
4
>>> len('abc'.encode('ascii'))
3
>>> len('我爱中国'.encode('utf-8'))
12

从上面可以看到,1个中文经过UTF-8编码后通常占用3个字节1个英文字符只占用1个字节

由于Python源代码本身也是一个文本文件,因此,为了保证使用的编码方式统一,防止含有中文导致乱码,以便Python解释器读取源文件是按照UTF-8的方式读取,最好在源文件头部加上:

1
2
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

第一行注释是为了告诉Linux/OS X系统,这是一个Python可执行程序,Windows系统会忽略这个注释。

第二行注释是为了告诉Python解释器,按照UTF-8的方式读取源代码,否则如果源文件中含有中文的话可能会导致乱码。

申明了UTF-8编码并不意味着你的.py文件就是UTF-8编码的,必须并且要确保文本编辑器正在使用UTF-8 without BOM编码; 如果.py文件本身使用UTF-8编码,并且也申明了# -*- coding: utf-8 -*-,打开命令提示符测试就可以正常显示中文。

格式化

常用格式化占位符如下表:

占位符 类型
%d 整型
%f 浮点型
%s 字符串
%x 十六进制整数
  • 通用用法
1
2
>>> print('I\'am %s, I am %d years old, grade percentage is %s%%' % ('langke', 18, '90'))
I'am langke, I am 18 years old, grade percentage is 90%
  • 使用format()函数
1
2
>>> print('我是{0}, 我今年的成绩提高了{1:.2f}%'.format('刘德华', 16.394))
我是刘德华, 我今年的成绩提高了16.39%

小结

目前使用最多的编码方式是UTF-8,如果没有特别的业务要求,尽量使用UTF-8编码、解码,以避免乱码以及其他不必要的麻烦。